package java_0305_sort;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.concurrent.ThreadLocalRandom;

/**
 * 排序的辅助类
 * 生成测试数组以及对排序算法进行测试
 * @author 美女
 * @date 2022/03/16 15:18
 **/
public class SortHelper {
    //获取一个随机数的对象
    private static final ThreadLocalRandom random=ThreadLocalRandom.current();

    /**
     * 1.在[left,right]上生成n个随机数
     * @param n
     * @param left
     * @param right
     * @return
     */
    public static int[] generateRandomArray(int n,int left,int right){
        int[] arr=new int[n];
        for (int i = 0; i < arr.length; i++) {
            arr[i]=random.nextInt(left,right);
        }
        return arr;
    }

    /**
     * 2.生成一个大小为n的近乎有序的数组
     * 思路：先生成一个有序的数组，再随机交换部分数
     * @param n
     * @param times 交换的次数-交换次数越小越有序
     * @return
     */
    public static int[] generateSortedArray(int n,int times){
        int[] arr=new int[n];
        for (int i = 0; i < n; i++) {
            arr[i] = i;
        }
        //交换部分元素，交换次数越小越有序
        for (int i = 0; i < times; i++) {
            //生成一个在[0,n]上的的随机数
            int a=random.nextInt(n);
            int b=random.nextInt(n);
            int temp=arr[a];
            arr[a]=arr[b];
            arr[b]=temp;
        }
        return arr;
    }
    /**
     * 3.生成一个arr的深拷贝数组
     * 为了测试不同排序算法的性能，需要在相同数据集进行测试
     */
    public static int[] arrCopy(int[] arr){
        return Arrays.copyOf(arr,arr.length);
    }
    /**
     * 4.测试性能
     * 根据传入的方法名称就能调用这些方法，需要借助反射【因为这些测试方法都是static方法，都根据类名称访问，没有对象】
     * 根据方法名称调用相应的排序方法对arr数组进行排序操作
     */
    public static void testSort(String sortName,int[] arr){//（）内是方法名称以及待排序的数组集合
        //获取一个类的反射对象:Class是个对象，它的类型是SevenSort类型
        Class<SevenSort> cls=SevenSort.class;
        try {
            //需要调用的方法对象
            Method method=cls.getDeclaredMethod(sortName,int[].class);
            //排序开始终止时间
            Long start=System.nanoTime();
            //排序方法的调用
            method.invoke(null,arr);//静态方法对象是null，在数组arr上进行排序
            Long end=System.nanoTime();
            if(isSorted(arr)){
                //排序算法正确
                System.out.println(sortName+"排序结束，共耗时："+(end-start)/1000000.0+"ms");
            }
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }
    /**
     * 判断数组是否有序
     * @param arr
     * @return
     */
    public static boolean isSorted(int[] arr){
        for (int i = 0; i < arr.length-1; i++) {
            if(arr[i]>arr[i+1]){
                System.out.println("sort error");
                return false;
            }
        }
        return true;
    }
}
